package com.lolc.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.lolc.LoLAutoCounterManager;
import com.lolc.bean.Champion;
import com.lolc.bean.Lane;
import com.lolc.bean.Pick;

public class Utils {
	
	/**
	 * Load all champions
	 * @param url
	 * @return
	 * @throws IOException
	 */
	@Deprecated
	public static List<Champion> loadChampions(String url, boolean isLocal) throws IOException {

       LoLAutoCounterManager.getLogger().info("Get champion list...");
        StringBuilder source = getContentWeb(url,isLocal);

        List<Champion> l = new ArrayList<Champion>();
        int i = 0;
        
        String beforeList="champList = [";
        String afterList="];";
        
        int startPostion=source.indexOf(beforeList, 0);
        int endPosition=source.indexOf(afterList, startPostion);
        
        String champList=source.substring(startPostion+beforeList.length(),
        		endPosition);
             
        String before="{";
        String after="}";
        int beforeSize = before.length();
        
        String beforeName = "\"name\":\"";
        String beforeId = "\",\"id\":\"";
        String afterId = "\",\"champ_image\"";
        int beforeNameSize = beforeName.length();
        int beforeIdSize = beforeId.length();
        
        while (champList.indexOf(before, i) != -1) {

        	int a = champList.indexOf(before, i);
        	String champion=  champList.substring(a + beforeSize,
        			champList.indexOf(after, a));

        	//System.out.println(champion);
        	String name =null;
        	if(champion.indexOf(beforeName, 0) != -1)
        	{
        		name = champion.substring(champion.indexOf(beforeName, 0) + beforeNameSize,
        				champion.indexOf(beforeId, 0));            
        	}

        	String id =null;
        	if(champion.indexOf(beforeId, 0) != -1)
        	{
        		id = champion.substring(champion.indexOf(beforeId, 0) + beforeIdSize,
        				champion.indexOf(afterId, 0));            
        	}
        	
        	Champion c = new Champion(id,name);
        	l.add(c);

        	i = a + beforeSize;
        }              
        
        return l;
	}

	/**
	 * Load all counters and synergies of each champions
	 * @param url
	 * @param list
	 * @throws IOException
	 */
	@Deprecated
	public static void updateSynergieCounter(String url, Champion champion, boolean isLocal)
			throws IOException {
		System.out.println("Get champion data...");	
		
		/*
		 * Strings used to get ratio for counter and syngerie
		 */
		String startDiv="picks-panel-interaction\">";
		String endDiv="</div>";
		Pattern getValuePattern  = Pattern.compile("> ?(\\d+)<");
		Pattern greenPattern  = Pattern.compile("<a class=\"label green\"(.*?)</a>");
		Pattern redPattern  = Pattern.compile("<a class=\"label red\"(.*?)</a>");
		
		//for (Champion champion : list) {
			/**
			 * TODO
			 */
			//COUNTER
			StringBuilder source = getContentWeb(url+"/"+champion.getId(),isLocal);
			//StringBuilder source = getContentWeb(url,isLocal);
						
			//SYNERGIE
			int j = source.indexOf("is Good with");
			System.out.println("Get synergie of "+champion.getName());
			String before = "picks-panel-link\" href=\"";
			String after = "\">";
			int beforeSize = before.length();
			
			List<Pick> ls = new ArrayList<Pick>();
			
			for (int count=0;count<Constant.NUMBER_SYNERGIES;count++) {

				int a = source.indexOf(before, j);
				String name = source.substring(a + beforeSize,
						source.indexOf(after, a));
				
				//Get interactions
				Float fgreenValue=0.0f;
				Float fredValue=0.0f;
				int divPosition = source.indexOf(startDiv, a);
				if(divPosition>-1)
				{
					String div = source.substring(divPosition + startDiv.length(),
							source.indexOf(endDiv, divPosition)).trim();

					//Green value
					Matcher matcher = greenPattern.matcher(div);
					if(matcher.find())
					{
						String temp = matcher.group();
						matcher = getValuePattern.matcher(temp);
						if(matcher.find())
						{
							fgreenValue=Float.valueOf(matcher.group(1));
						}
					}

					//Red value
					matcher = redPattern.matcher(div);
					if(matcher.find())
					{
						String temp = matcher.group();							
						matcher = getValuePattern.matcher(temp);
						if(matcher.find())
						{
							fredValue=Float.valueOf(matcher.group(1));
						}
					}
				}
				
				Float ratio=0.0f;
				if(fredValue>0)
				{
					ratio=fgreenValue/fredValue;
				}
				System.out.println("->"+name+" : green="+fgreenValue+" ,red="+fredValue+" ,ratio="+ratio);
				Pick c = new Pick(new Champion(
						name),ratio);
				ls.add(c);
				j = a + beforeSize;
			}
			
			champion.setSynergies(ls);		
			
			//LANES
			List<Lane> lanes = new ArrayList<Lane>();
			Pattern infoTagPattern  = Pattern.compile("(<div class=\"champinfo_tag\">(.*?)</div>)");
			Matcher matcher = infoTagPattern.matcher(source);
			 
			while (matcher.find()) {
			    String championInfoTag = matcher.group(); 
				
			    if(Pattern.compile(Constant.JUNGLER_HTML_REGEXP).matcher(championInfoTag).find())
			    {
			    	lanes.add(new Lane("jungler"));
			    }
			    
			    if(Pattern.compile(Constant.TOP_HTML_REGEXP).matcher(championInfoTag).find())
			    {
			    	lanes.add(new Lane("top"));
			    }
			    
			    if(Pattern.compile(Constant.MID_HTML_REGEXP).matcher(championInfoTag).find())
			    {
			    	lanes.add(new Lane("mid"));
			    }
			    
			    if(Pattern.compile(Constant.BOTTOM_HTML_REGEXP).matcher(championInfoTag).find())
			    {
			    	lanes.add(new Lane("bottom"));
			    }
			}
			champion.setLanes(lanes);
				
			Pattern generalPattern  = Pattern.compile("<a href=\"#General\" data-toggle=\"tab\"  onClick=\"ajaxLaneCounters\\('([0-9]*)', ([0-9]*)(.*?)</a>");
			Matcher matcher1 = generalPattern.matcher(source);
			System.out.println("Get general url");
			if(matcher1.find())
			{
				String champId = matcher1.group(1);
				String laneId = matcher1.group(2);

				source = getContentWeb(url+"/../ajax/"+champId+"/lane/"+laneId,isLocal);
			}
			
			//StringBuilder source = getContentWeb(url,isLocal);
			j = source.indexOf("is Bad against");
			System.out.println("Get counters of "+champion.getName());
			before = "picks-panel-link\" href=\"";
			after = "\">";
			beforeSize = before.length();
			
			List<Pick> lc = new ArrayList<Pick>();			
			for (int count=0;count<Constant.NUMBER_COUNTERS;count++) {

				int a = source.indexOf(before, j);
				String name = source.substring(a + beforeSize,
						source.indexOf(after, a));
				
				//Ratio
				//Get interactions
				Float fgreenValue=0.0f;
				Float fredValue=0.0f;
				int divPosition = source.indexOf(startDiv, a);
				if(divPosition>-1)
				{
					String div = source.substring(divPosition + startDiv.length(),
							source.indexOf(endDiv, divPosition)).trim();

					//Green value
					Matcher matcherRatio = greenPattern.matcher(div);
					if(matcherRatio.find())
					{
						String temp = matcherRatio.group();
						matcherRatio = getValuePattern.matcher(temp);
						if(matcherRatio.find())
						{
							fgreenValue=Float.valueOf(matcherRatio.group(1));
						}
					}

					//Red value
					matcherRatio = redPattern.matcher(div);
					if(matcherRatio.find())
					{
						String temp = matcherRatio.group();							
						matcherRatio = getValuePattern.matcher(temp);
						if(matcherRatio.find())
						{
							fredValue=Float.valueOf(matcherRatio.group(1));
						}
					}
				}

				Float ratio=0.0f;
				if(fredValue>0)
				{
					ratio=fgreenValue/fredValue;
				}
				
				Pick c = new Pick(new Champion(name),ratio);
				System.out.println("->"+name+" : green="+fgreenValue+" ,red="+fredValue+" ,ratio="+ratio);
				lc.add(c);
				j = a + beforeSize;
			}
			
			champion.setCounters(lc);		
		//}
		
		System.out.println("Get champion data...Done");
	}
	
	/**
	 * Get HTML content from web page
	 * @param url
	 * @param isLocal
	 * @return
	 * @throws MalformedURLException
	 * @throws IOException
	 * @throws UnsupportedEncodingException
	 */
	private static StringBuilder getContentWeb(String url, boolean isLocal)
			throws MalformedURLException, IOException,
			UnsupportedEncodingException {
		
		/**
		 * TODO  uncomment commented lines
		 */
		BufferedReader reader;
		if(isLocal)
		{
			reader = new BufferedReader(new FileReader(new File(url)));			
		}
		else
		{
			URL webPage = new URL(url);

			if(Constant.HTTP_PROXY_HOST!=null && Constant.HTTP_PROXY_PORT!=null)
			{
				Properties systemProperties = System.getProperties();
				systemProperties.setProperty("http.proxyHost", Constant.HTTP_PROXY_HOST);
				systemProperties.setProperty("http.proxyPort", Constant.HTTP_PROXY_PORT);
			}

			URLConnection connection = webPage.openConnection();
			reader = new BufferedReader(new InputStreamReader(
					connection.getInputStream(), "UTF-8"));
		}
				
		String inputLine;
		StringBuilder source = new StringBuilder();
		while ((inputLine = reader.readLine()) != null)
			source.append(inputLine);
		reader.close();
		return source;
	}
	
	/**
	 * Save all champions info in XML file
	 * @param list
	 */
	public static void saveChampionsXMLFile(List<Champion> list, String xmlFilePath)
	{

		try {
			DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

			// root elements
			Document doc = docBuilder.newDocument();
			Element rootElement = doc.createElement(Constant.XML_FILE_CHAMPIONS_ELEMENT);
			doc.appendChild(rootElement);
			
			DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
			Date today = Calendar.getInstance().getTime();        
			rootElement.setAttribute(Constant.XML_FILE_LOAD_DATE_ATTRIBUTE, df.format(today));

			for(Champion champ : list)
			{
				Element champion = doc.createElement(Constant.XML_FILE_CHAMPION_ELEMENT);
				rootElement.appendChild(champion);

				// set attribute to staff element
				champion.setAttribute(Constant.XML_FILE_NAME_ATTRIBUTE, champ.getName());
				champion.setAttribute(Constant.XML_FILE_ID_ATTRIBUTE, champ.getId());
				
				//Decimal format for float to string conversion
				DecimalFormatSymbols symbols = new DecimalFormatSymbols();
				symbols.setDecimalSeparator('.');
				DecimalFormat decimalFormat = new DecimalFormat("0.00");
				decimalFormat.setDecimalFormatSymbols(symbols);
				
				//Counters
				if(champ.getCounters()!=null)
				{
					Element counters = doc.createElement(Constant.XML_FILE_COUNTERS_ELEMENT);
					champion.appendChild(counters);
					for(Pick count : champ.getCounters())
					{
						Element counter = doc.createElement(Constant.XML_FILE_COUNTER_ELEMENT);
						counters.appendChild(counter);
						counter.setAttribute(Constant.XML_FILE_CHAMPIONID_ATTRIBUTE,count.getChampion().getId());
						counter.setAttribute(Constant.XML_FILE_RATIO_ATTRIBUTE,decimalFormat.format(count.getRatio()));
					}
				}
				
				//Synergies
				if(champ.getSynergies()!=null)
				{
					Element counters = doc.createElement(Constant.XML_FILE_SYNERGIES_ELEMENT);
					champion.appendChild(counters);
					for(Pick synergie : champ.getSynergies())
					{
						Element counter = doc.createElement(Constant.XML_FILE_SYNERGIE_ELEMENT);
						counters.appendChild(counter);
						counter.setAttribute(Constant.XML_FILE_CHAMPIONID_ATTRIBUTE,synergie.getChampion().getId());
						counter.setAttribute(Constant.XML_FILE_RATIO_ATTRIBUTE,decimalFormat.format(synergie.getRatio()));
					}
				}
				
				//Lanes
				if(champ.getLanes()!=null)
				{
					Element lanes = doc.createElement(Constant.XML_FILE_LANES_ELEMENT);
					champion.appendChild(lanes);
					for(Lane lane : champ.getLanes())
					{
						Element laneElt = doc.createElement(Constant.XML_FILE_LANE_ELEMENT);
						lanes.appendChild(laneElt);
						laneElt.setAttribute(Constant.XML_FILE_TYPE_ATTRIBUTE,lane.getId());
						
						//Counters
						Element counters = doc.createElement(Constant.XML_FILE_COUNTERS_ELEMENT);
						laneElt.appendChild(counters);
						for(Pick count : lane.getCounters())
						{
							Element counter = doc.createElement(Constant.XML_FILE_COUNTER_ELEMENT);
							counters.appendChild(counter);
							counter.setAttribute(Constant.XML_FILE_CHAMPIONID_ATTRIBUTE,count.getChampion().getId());
							counter.setAttribute(Constant.XML_FILE_RATIO_ATTRIBUTE,decimalFormat.format(count.getRatio()));
						}
					}					
				}
			}
			
			// write the content into xml file
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
			DOMSource source = new DOMSource(doc);
			StreamResult result = new StreamResult(new File(xmlFilePath));

			// Output to console for testing
			transformer.transform(source, result);

			System.out.println("File saved");
		} catch (ParserConfigurationException pce) {
			LoLAutoCounterManager.getLogger().error(pce.getCause());
		} catch (TransformerException tfe) {
			LoLAutoCounterManager.getLogger().error(tfe.getCause());
		}		
	}
	
	/**
	 * Load XML file with all champions info
	 */
	public static List<Champion> loadChampionsXMLFile(String xmlFilePath)
	{
		List<Champion> l = new ArrayList<Champion>();

		FileInputStream file;
		try {
			file = new FileInputStream(new File(xmlFilePath));
			DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();           
			DocumentBuilder builder =  builderFactory.newDocumentBuilder();

			Document xmlDocument = builder.parse(file);

			NodeList nList = xmlDocument.getElementsByTagName(Constant.XML_FILE_CHAMPION_ELEMENT);

			for (int temp = 0; temp < nList.getLength(); temp++) {

				Node nNode = nList.item(temp);
				if (nNode.getNodeType() == Node.ELEMENT_NODE) {

					Element echampionElement = (Element) nNode;

					String name=echampionElement.getAttribute(Constant.XML_FILE_NAME_ATTRIBUTE);
					String id=echampionElement.getAttribute(Constant.XML_FILE_ID_ATTRIBUTE);
					Champion champion =  new Champion(id, name);

					//Counters
					List<Pick> counters = new ArrayList<Pick>();
					if(echampionElement.getElementsByTagName(Constant.XML_FILE_COUNTERS_ELEMENT)!=null)
					{
						Element ecountersElt = (Element) echampionElement.getElementsByTagName(Constant.XML_FILE_COUNTERS_ELEMENT).item(0);
						if(ecountersElt!=null && ecountersElt.getElementsByTagName(Constant.XML_FILE_COUNTER_ELEMENT)!=null)
						{	      					
							NodeList ncounterList = ecountersElt.getElementsByTagName(Constant.XML_FILE_COUNTER_ELEMENT);


							for (int i = 0; i < ncounterList.getLength(); i++) {
								Node ncounterNode = ncounterList.item(i);
								if (ncounterNode.getNodeType() == Node.ELEMENT_NODE) {
									Element ecounterElement = (Element) ncounterNode;

									String championid=ecounterElement.getAttribute(Constant.XML_FILE_CHAMPIONID_ATTRIBUTE);
									String ratio=ecounterElement.getAttribute(Constant.XML_FILE_RATIO_ATTRIBUTE);

									Pick c = new Pick(new Champion(championid),Float.parseFloat(ratio));
									counters.add(c);
								}
							}
						}
						champion.setCounters(counters);

						//Synergies
						List<Pick> synergies = new ArrayList<Pick>();
						if(echampionElement.getElementsByTagName(Constant.XML_FILE_SYNERGIES_ELEMENT)!=null)
						{
							Element esynergiesElt = (Element) echampionElement.getElementsByTagName(Constant.XML_FILE_SYNERGIES_ELEMENT).item(0);
							if(esynergiesElt!=null && esynergiesElt.getElementsByTagName(Constant.XML_FILE_SYNERGIE_ELEMENT)!=null)
							{	      					
								NodeList nsynergieList = esynergiesElt.getElementsByTagName(Constant.XML_FILE_SYNERGIE_ELEMENT);
								for (int i = 0; i < nsynergieList.getLength(); i++) {

									Node nsynergieNode = nsynergieList.item(i);

									if (nsynergieNode.getNodeType() == Node.ELEMENT_NODE) {
										Element esynergieElement = (Element) nsynergieNode;

										String championid=esynergieElement.getAttribute(Constant.XML_FILE_CHAMPIONID_ATTRIBUTE);
										String ratio=esynergieElement.getAttribute(Constant.XML_FILE_RATIO_ATTRIBUTE);

										Pick s = new Pick(new Champion(championid),Float.parseFloat(ratio));
										synergies.add(s);
									}
								}
							}
						}	 
						champion.setSynergies(synergies);
						
						//Lanes
						List<Lane> lanes = new ArrayList<Lane>();
						if(echampionElement.getElementsByTagName(Constant.XML_FILE_LANES_ELEMENT)!=null)
						{
							Element elanesElt = (Element) echampionElement.getElementsByTagName(Constant.XML_FILE_LANES_ELEMENT).item(0);
							if(elanesElt!=null && elanesElt.getElementsByTagName(Constant.XML_FILE_LANES_ELEMENT)!=null)
							{	      					
								NodeList nlaneList = elanesElt.getElementsByTagName(Constant.XML_FILE_LANE_ELEMENT);
								for (int i = 0; i < nlaneList.getLength(); i++) {

									Node nlaneNode = nlaneList.item(i);

									if (nlaneNode.getNodeType() == Node.ELEMENT_NODE) {
										Element elaneElement = (Element) nlaneNode;

										String laneid=elaneElement.getAttribute(Constant.XML_FILE_TYPE_ATTRIBUTE);
										List<Pick> laneCounters = new ArrayList<Pick>();
										
										//Get counters
										Element eLaneCountersElt = (Element) elaneElement.getElementsByTagName(Constant.XML_FILE_COUNTERS_ELEMENT).item(0);
										if(eLaneCountersElt!=null && eLaneCountersElt.getElementsByTagName(Constant.XML_FILE_COUNTER_ELEMENT)!=null)
										{	      					
											NodeList ncounterList = eLaneCountersElt.getElementsByTagName(Constant.XML_FILE_COUNTER_ELEMENT);

											for (int j = 0; j < ncounterList.getLength(); j++) {
												Node ncounterNode = ncounterList.item(j);
												if (ncounterNode.getNodeType() == Node.ELEMENT_NODE) {
													Element ecounterElement = (Element) ncounterNode;

													String championid=ecounterElement.getAttribute(Constant.XML_FILE_CHAMPIONID_ATTRIBUTE);
													String ratio=ecounterElement.getAttribute(Constant.XML_FILE_RATIO_ATTRIBUTE);

													Pick c = new Pick(new Champion(championid),Float.parseFloat(ratio));
													laneCounters.add(c);
												}
											}
										}
										Lane lane=new Lane(laneid);
										lane.setCounters(laneCounters);
										lanes.add(lane);
									}
								}
							}
						}	 
						champion.setLanes(lanes);
					}
					l.add(champion);
				}
			}

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			LoLAutoCounterManager.getLogger().error(e.getCause());
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			LoLAutoCounterManager.getLogger().error(e.getCause());
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			LoLAutoCounterManager.getLogger().error(e.getCause());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			LoLAutoCounterManager.getLogger().error(e.getCause());
		}          

		return l;
	}
	
	/**
	 * Load XML file with lane list
	 * @param xmlFilePath
	 * @return
	 */
	public static List<Lane> loadLanesXMLFile(String xmlFilePath)
	{
		List<Lane> l = new ArrayList<Lane>();

		FileInputStream file;
		try {
			file = new FileInputStream(new File(xmlFilePath));
			DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();           
			DocumentBuilder builder =  builderFactory.newDocumentBuilder();

			Document xmlDocument = builder.parse(file);

			NodeList nList = xmlDocument.getElementsByTagName(Constant.XML_FILE_LANE_ELEMENT);

			for (int i = 0; i < nList.getLength(); i++) {

				Node nNode = nList.item(i);

				if (nNode.getNodeType() == Node.ELEMENT_NODE) {

					Element elaneElement = (Element) nNode;

					String name=elaneElement.getAttribute(Constant.XML_FILE_NAME_ATTRIBUTE);
					String id=elaneElement.getAttribute(Constant.XML_FILE_ID_ATTRIBUTE);

					Lane lane = new Lane(id, name);
					l.add(lane);
				}				
			}
		}
		 catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			 LoLAutoCounterManager.getLogger().error(e.getCause());
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			LoLAutoCounterManager.getLogger().error(e.getCause());
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			LoLAutoCounterManager.getLogger().error(e.getCause());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			LoLAutoCounterManager.getLogger().error(e.getCause());
		}          

		return l;
	}
}
